package com.modern.webapp.action;

import com.opensymphony.xwork2.Preparable;
import com.modern.service.GenericManager;
import com.modern.model.TypingSource;
import com.modern.webapp.action.BaseAction;

import java.util.Arrays;
import java.util.List;

public class TypingSourceAction extends BaseAction implements Preparable {
	private GenericManager<TypingSource, Long> typingSourceManager;
	private List typingSources;
	private TypingSource typingSource;
	private Long sourceId;
	private List<String> sourceContent;
	private String userText;
	private String orignalText;
	private int levenshtein;

	public int getLevenshtein() {
		return levenshtein;
	}

	public void setLevenshtein(int levenshtein) {
		levenshtein = levenshtein;
	}

	public String getUserText() {
		return userText;
	}

	public void setUserText(String userText) {
		this.userText = userText;
	}

	public String getOrignalText() {
		return orignalText;
	}

	public void setOrignalText(String orignalText) {
		this.orignalText = orignalText;
	}

	public List getSourceContent() {
		return sourceContent;
	}

	public void setSourceContent(List sourceContent) {
		this.sourceContent = sourceContent;
	}

	public void setTypingSourceManager(
			GenericManager<TypingSource, Long> typingSourceManager) {
		this.typingSourceManager = typingSourceManager;
	}

	public List getTypingSources() {
		return typingSources;
	}

	/**
	 * Grab the entity from the database before populating with request
	 * parameters
	 */
	public void prepare() {
		if (getRequest().getMethod().equalsIgnoreCase("post")) {
			// prevent failures on new
			String typingSourceId = getRequest().getParameter(
					"typingSource.sourceId");
			if (typingSourceId != null && !typingSourceId.equals("")) {
				typingSource = typingSourceManager
						.get(new Long(typingSourceId));
			}
		}
	}

	public String list() {
		typingSources = typingSourceManager.getAll();
		return SUCCESS;
	}

	public void setSourceId(Long sourceId) {
		this.sourceId = sourceId;
	}

	public TypingSource getTypingSource() {
		return typingSource;
	}

	public void setTypingSource(TypingSource typingSource) {
		this.typingSource = typingSource;
	}

	public String delete() {
		typingSourceManager.remove(typingSource.getSourceId());
		saveMessage(getText("typingSource.deleted"));

		return SUCCESS;
	}

	public String edit() {
		if (sourceId != null) {
			typingSource = typingSourceManager.get(sourceId);
		} else {
			typingSource = new TypingSource();
		}

		return SUCCESS;
	}

	public String save() throws Exception {
		if (cancel != null) {
			return "cancel";
		}

		if (delete != null) {
			return delete();
		}

		boolean isNew = (typingSource.getSourceId() == null);

		typingSourceManager.save(typingSource);

		String key = (isNew) ? "typingSource.added" : "typingSource.updated";
		saveMessage(getText(key));

		if (!isNew) {
			return INPUT;
		} else {
			return SUCCESS;
		}
	}

	public String typingTest() throws Exception {
		if (sourceId != null) {
			typingSource = typingSourceManager.get(sourceId);
		} else {
			typingSource = new TypingSource();
		}
		String content = typingSource.getSourceContent();
		String[] temp = content.split("\n");
		sourceContent = Arrays.asList(temp);

		return SUCCESS;
	}

	public String compare() throws Exception {
		levenshtein = LD(orignalText, userText);
		System.out.println("================"+levenshtein);
		return SUCCESS;
	}

	// ****************************
	// Get minimum of three values
	// ****************************
	private int Minimum(int a, int b, int c) {
		int mi;

		mi = a;
		if (b < mi) {
			mi = b;
		}
		if (c < mi) {
			mi = c;
		}
		return mi;

	}

	// *****************************
	// Compute Levenshtein distance
	// *****************************
	public int LD(String s, String t) {
		int d[][]; // matrix
		int n; // length of s
		int m; // length of t
		int i; // iterates through s
		int j; // iterates through t
		char s_i; // ith character of s
		char t_j; // jth character of t
		int cost; // cost

		// Step 1

		n = s.length();
		m = t.length();
		if (n == 0) {
			return m;
		}
		if (m == 0) {
			return n;
		}
		d = new int[n + 1][m + 1];

		// Step 2

		for (i = 0; i <= n; i++) {
			d[i][0] = i;
		}

		for (j = 0; j <= m; j++) {
			d[0][j] = j;
		}
		// Step 3
		for (i = 1; i <= n; i++) {
			s_i = s.charAt(i - 1);
			// Step 4
			for (j = 1; j <= m; j++) {
				t_j = t.charAt(j - 1);
				// Step 5
				if (s_i == t_j) {
					cost = 0;
				} else {
					cost = 1;
				}
				// Step 6
				d[i][j] = Minimum(d[i - 1][j] + 1, d[i][j - 1] + 1,
						d[i - 1][j - 1] + cost);
			}
		}
		// Step 7
		return d[n][m];
	}
}